#include "stm32f10x.h"                  // Device header
#include "MySPI.h"
#include "W25Q64_Ins.h"

/************************************************************************************************************
* Function name : W25Q64_Init
* Description   : 初始化 W25Q64
* Parameter     : 
* Return        : 
************************************************************************************************************/
void W25Q64_Init(void)
{
	// 初始化 SPI
	MySPI_Init();
}


/************************************************************************************************************
* Function name : W25Q64_ReadID
* Description   : 读取厂商ID
* Parameter     : 
* Return        : 
************************************************************************************************************/
void W25Q64_ReadID(uint8_t *MID, uint16_t *DID)
{
	// 开始时序
	MySPI_Start();
	
	// 获得MID
	MySPI_SwapByte(W25Q64_JEDEC_ID);
	*MID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	
	// 设备ID
	*DID = MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	*DID <<= 8;
	*DID |= MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	
	// 结束时序
	MySPI_Stop();
}


/************************************************************************************************************
* Function name : W25Q64_WriteEnable
* Description   : 写使能
* Parameter     : 
* Return        : 
************************************************************************************************************/
void W25Q64_WriteEnable(void)
{
	// 开始时序
	MySPI_Start();
	
	// 写使能
	MySPI_SwapByte(W25Q64_WRITE_ENABLE);
	
	// 结束时序
	MySPI_Stop();
}


/************************************************************************************************************
* Function name : W25Q64_WaitBusy
* Description   : 等待状态寄存器的 busy 为 0
* Parameter     : 
* Return        : 
************************************************************************************************************/
void W25Q64_WaitBusy(void)
{
	uint32_t Timeout = 100000;
	
	// 开始时序
	MySPI_Start();
	
	// 发送指令
	MySPI_SwapByte(W25Q64_READ_STATUS_REGISTER_1);
	
	// 发送 dummyByte 读取寄存器值
	while((MySPI_SwapByte(W25Q64_DUMMY_BYTE) & 0x01) == 0x01)
	{
		Timeout--;
		if(Timeout == 0)
		{
		    break;
		}
	}
	
	// 结束时序
	MySPI_Stop();
}


/************************************************************************************************************
* Function name : W25Q64_PageProgram
* Description   : 页编程
* Parameter     : 
* Return        : 
************************************************************************************************************/
void W25Q64_PageProgram(uint32_t Address, uint8_t *DataArray, uint16_t Count)
{
	uint16_t i = 0;
	
	// 写使能
	W25Q64_WriteEnable();
	
	// 开始时序
	MySPI_Start();
	
	// 发送指令
	MySPI_SwapByte(W25Q64_PAGE_PROGRAM);
	
	// 发送地址
	MySPI_SwapByte(Address >> 16);
	MySPI_SwapByte(Address >> 8);
	MySPI_SwapByte(Address);
	
	// 写入数据
	for(i = 0; i < Count; i++)
	{
		MySPI_SwapByte(DataArray[i]);
	}
	
	// 结束时序
	MySPI_Stop();
	
	// 每次写入后, 都等 BUSY 清零了再退出
	W25Q64_WaitBusy();
}


/************************************************************************************************************
* Function name : W25Q64_SectorErase
* Description   : 擦除
* Parameter     : 
* Return        : 
************************************************************************************************************/
void W25Q64_SectorErase(uint32_t Address)
{
	// 写使能
	W25Q64_WriteEnable();
	
	// 开始时序
	MySPI_Start();
	
	// 发送指令
	MySPI_SwapByte(W25Q64_SECTOR_ERASE_4KB);
	
	// 发送地址
	MySPI_SwapByte(Address >> 16);
	MySPI_SwapByte(Address >> 8);
	MySPI_SwapByte(Address);
	
	// 结束时序
	MySPI_Stop();
	
	// 每次写入后, 都等 BUSY 清零了再退出
	W25Q64_WaitBusy();
}


/************************************************************************************************************
* Function name : W25Q64_ReadData
* Description   : 读取数据
* Parameter     : 
* Return        : 
************************************************************************************************************/
void W25Q64_ReadData(uint32_t Address, uint8_t *DataArray, uint32_t Count)
{
	uint32_t i = 0;
	
	// 开始时序
	MySPI_Start();
	
	// 发送指令
	MySPI_SwapByte(W25Q64_READ_DATA);
	
	// 发送地址
	MySPI_SwapByte(Address >> 16);
	MySPI_SwapByte(Address >> 8);
	MySPI_SwapByte(Address);
	
	// 读取数据
	for(i = 0; i < Count; i++)
	{
		DataArray[i] = MySPI_SwapByte(W25Q64_DUMMY_BYTE);
	}
	
	// 结束时序
	MySPI_Stop();
}